package under.wsl.decode;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.Normalizer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class DefaultJsonDecode implements JsonDecodeI{
	
	private SimpleDateFormat formatas = null;
	
	public DefaultJsonDecode() {
		super();
		String dataz = "dd-MM-yyyy";
        this.formatas = new SimpleDateFormat(dataz);
	}	
	
	@Override
	public String valueToString(Object objvalue, String typeS) {
		if(objvalue==null){
			return null;
		}
		String concS = "\"";        
		typeS = typeS.toLowerCase();
    	if(typeS.equals("int")||typeS.indexOf("boolean") > -1||typeS.indexOf("object") > -1){
    		concS = "";
    	}
    	if(typeS.equals("java.lang.string")){           
            return concS+objvalue.toString().trim()+concS;
     	}else if(typeS.indexOf("date") > -1){           	
        	Date valorDoBanco = (Date) objvalue;
            String data = this.formatas.format(valorDoBanco );           
            return concS+data+concS;  
    	}else if(typeS.indexOf("list") > -1){    			
			String acumL = "";
			List<?> myobjl = (List<?>) objvalue;
			int tmL = myobjl.size();
    		objvalue.getClass().getName();
    		String  subtipo = "";
    		if(tmL>0){
    			subtipo =  myobjl.get(0).getClass().getName().toLowerCase();
    			if(subtipo.matches(".*(string|int|date|boolean|char)$")){        				
            		for(int x =0;x<tmL;x++){     			
            			acumL += ","+this.valueToString((Object) myobjl.get(x),subtipo);
            		}    		
            		if(acumL.length() > 0){
            			acumL =	acumL.substring(1);
            		}    		
            		return "["+acumL+"]";   
    			}else{        				
    				return this.ListToJson((List<?>) objvalue);
    			}        			
    		}
    		return null;
    	}else if(typeS.indexOf("ljava") > -1){
    		String acumL = "";    	
    		String[] myobjl =  (String[]) objvalue;
    		for(int x =0;x < myobjl.length  ;x++){
    			acumL += ","+this.valueToString((Object) myobjl[x],myobjl[x].getClass().getName());
    		}    		
    		if(acumL.length() > 0){
    			acumL =	acumL.substring(1);
    		}    		
    		return "["+acumL+"]";
    	}else{           
           return concS+objvalue+concS;
    	}
	}
	


	private String ListToJson(List<?> p_list){
		int tmLObj = p_list.size();
		if(tmLObj > 0){	
			Class<?> classe = p_list.get(0).getClass();	        
	        String acuml1 = "";
	        for (Method m : classe.getMethods()) {
	           if(m.getName().indexOf("get") == 0 && !m.getName().equals("getClass")){
	        		String NameAttri =  m.getName().substring(3,m.getName().length());
	        		NameAttri = NameAttri.substring(0,1).toLowerCase()+NameAttri.substring(1,NameAttri.length());
	                try {                	
	                	acuml1 += ",\""+NameAttri+"\":[";  
	                	String acuml2 = "";                	
	                    for(int x = 0;x <tmLObj;x++){	                    	
	                    	acuml2 +=","+this.valueToString(m.invoke(p_list.get(x)),m.getReturnType().getName());	                
	                    }	
	                    if(acuml2.length() > 0){
	                    	acuml2 = acuml2.substring(1);
	                    }	                    
	                    acuml1 += acuml2+"]";                    
	                } catch (Throwable t) {                  
	                    System.out.println(" erro in toJson list "+m.getName()+" " + t.getCause());
	                }
	        	}	        	
	        }
	        if(acuml1.length()>0){
	        	acuml1 = acuml1.substring(1);
	        }
	        return "{"+acuml1+"}";
		}
		return null;		
	}
	
	@Override
	public String toJson(List<?> p_list) {
		return this.ListToJson(p_list);
	}
	
	
	@Override
	public String toJson(Object objvalue) {
		if(objvalue!=null){
			Class<?> classe = objvalue.getClass();	        
	        String acuml1 = "";
	        for (Method m : classe.getMethods()) {
	           if(m.getName().indexOf("get") == 0 && !m.getName().equals("getClass")){
	        		String NameAttri =  m.getName().substring(3,m.getName().length());
	        		NameAttri = NameAttri.substring(0,1).toLowerCase()+NameAttri.substring(1,NameAttri.length());
	        		if(NameAttri.length() > 0){
		                try {                	
		                	acuml1 += ",\""+NameAttri+"\":";  
		                	String acuml2 = "";                                     	
		                    acuml2 +=","+this.valueToString(m.invoke(objvalue),m.getReturnType().getName());                
		                    if(acuml2.length() > 0){
		                    	acuml2 = acuml2.substring(1);
		                    }
		                    acuml1 += acuml2;                    
		                } catch (Throwable t) {                  
		                    System.out.println(" erro in toJson obj "+m.getName()+" : "+t.getCause());
		                }
	        		}
	        	}	        	
	        }
	        if(acuml1.length()>0){
	        	acuml1 = acuml1.substring(1);
	        }
	        return "{"+acuml1+"}";
		}
		return null;
	}

	public String mapToJson(Map<String, String[]> p_list) {	
		String acuml1 = "";
		for (String key : p_list.keySet()) { 
			String[] value = p_list.get(key);
			//this.valueToString(value,value.getClass().getName())
			acuml1 += ",\""+key+"\":" + this.valueToString(value,value.getClass().getName());
		}	
        if(acuml1.length()>0){
        	acuml1 = acuml1.substring(1);
        }
        return "{"+acuml1+"}";
	}
	
	@Override
	public <T> T fromJson(String json, Type typeOfT) {		
		//T target = (T)  typeOfT. ;
		String classeT = typeOfT+"";
		classeT = classeT.replaceFirst("class ","");
		Class<?> classe=null;
		try {
			classe = Class.forName(classeT);
		} catch (Exception e) {
			System.out.println("erro fromJson:"+e.getMessage());
		}		
		T target=null;
		try {
			target = (T) classe.newInstance();
		} catch (Exception e) {
			System.out.println("erro fromJson:"+e.getMessage());
		}
				
				
        for (Method m : classe.getMethods()) {
           if(m.getName().indexOf("set") == 0 && !m.getName().equals("getClass")){
        		String NameAttri =  m.getName().substring(3,m.getName().length());
        		NameAttri = NameAttri.substring(0,1).toLowerCase()+NameAttri.substring(1,NameAttri.length());
        		if(NameAttri.length() > 0){       			
        		      String pattern = "\""+NameAttri+"\":\"([^,\"]+)";
        		      // Create a Pattern object
        		      Pattern r = Pattern.compile(pattern);
        		      // Now create matcher object.
        		      Matcher mat = r.matcher(json);
        		      if (mat.find( )) {        	       		         
     	                try {           	                	
     	                  Class<?> parametros[] = m.getParameterTypes();     	                	
    	                	m.invoke(target,this.getValorConvertido(parametros[0].getCanonicalName(), mat.group(1)));                  
    	                } catch (Exception e) {                  
    	                    System.out.println(" erro in fromJson obj "+m.getName()+" : "+e.getMessage());
    	                }
        		      }        			
        		}
        	}	        	
        } 		
		return target;
	}
	
	@Override
    public Object getValorConvertido(String canonicalName, String valor) {
        Object convertido = null;
        SimpleDateFormat formatador = new SimpleDateFormat("dd-MM-yyyy");
       
        if (canonicalName.equals("int")) {
            convertido = Integer.parseInt(valor);
        } else if (canonicalName.equals("java.lang.Integer")) {
            convertido = new Integer(valor);
        } else if (canonicalName.equals("float")) {
            convertido = Float.parseFloat(valor.replace(',', '.'));
        } else if (canonicalName.equals("java.lang.Float")) {
            convertido = new Float(valor.replace(',', '.'));
        } else if (canonicalName.equals("java.lang.Boolean")) {            
            convertido = Boolean.parseBoolean(valor);
        } else if (canonicalName.equals("boolean")) {
            convertido = Boolean.parseBoolean(valor);
        } else if (canonicalName.equals("java.util.Date")) {
            try {
                convertido = formatador.parse(valor);
            } catch (Exception e) {
                System.out.println(e.getMessage().toString());
            }
        } else if (canonicalName.equals("java.lang.Short")) {
            convertido = new Short(valor.replace(',', '.'));
        }else if (canonicalName.equals("short")) {
            convertido = Short.parseShort(valor.replace(',', '.'));
        }else if (canonicalName.equals("java.math.BigDecimal")) {
            convertido = new BigDecimal(valor.replace(',', '.'));
        }else if (canonicalName.equals("java.math.BigInteger")) {
            convertido = new BigInteger(valor);
        }else if (canonicalName.equals("java.lang.String")) {
        	String nfdNormalizedString = Normalizer.normalize(valor, Normalizer.Form.NFD); 
            Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
            convertido = pattern.matcher(nfdNormalizedString).replaceAll("");   
        }else if (canonicalName.equals("java.lang.Character")||canonicalName.equals("char")){
          convertido =  valor.charAt(0);
        }        
        return convertido;
    }
	
}
